package model

import (
	"errors"
	"fmt"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/xanzy/go-gitlab"

	"devOpsApi/config/ymlgo"
)

type TreeNode struct {
	ID               string     `json:"id"`
	Name             string     `json:"name"`
	Type             string     `json:"type"`
	Path             string     `json:"path"`
	Mode             string     `json:"mode"`
	CommitTitle      string     `json:"commitTitle"`
	CommitCreateTime *time.Time `json:"commitCreateTime"`
}

type GitResult struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	TokenType    string `json:"token_type"`
	Scope        string `json:"scope"`
	CreatedAt    int64  `json:"created_at"`
}

type GitLab struct {
	Client *gitlab.Client
}

type GitUserLab struct {
	Client *gitlab.Client
}

func NewGitResult() *GitResult {
	return &GitResult{}
}
func NewAdminGitUserLab() *GitUserLab {
	return &GitUserLab{Client: NewGitlab().Client}
}
func (m *GitUserLab) List(page, pagesize uint, k string) ([]*gitlab.Project, uint, uint) {
	ListTreeOptions := &gitlab.ListProjectsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    int(page),
			PerPage: int(pagesize),
		},
		Membership: gitlab.Bool(true), //自己和别人分享给自己的项目
		Search:     gitlab.String(k),
		Simple:     gitlab.Bool(true),
	}
	listNodes, pageInfo, _ := m.Client.Projects.ListProjects(ListTreeOptions)
	return listNodes, uint(pageInfo.TotalItems), uint(pageInfo.TotalPages)
}

func NewGitlab() *GitLab {
	config := ymlgo.NewConfigSysBase()
	git, _ := gitlab.NewClient(config.GitLabRootAccessToken, gitlab.WithBaseURL(config.GitLabServer))
	gitLab := &GitLab{
		Client: git,
	}
	return gitLab
}

// 获取用户git对象 url[0]为自定义git地址
func NewUserGitlab(uid int, httpUser ...string) (*GitUserLab, error) {
	git := new(gitlab.Client)
	var err error
	//https://username:password@git.com/test.git
	//如果url中包含特殊字符 有可能出现url.parse解析失败的问题
	if len(httpUser) > 0 && httpUser[0] != "" {
		urlParse, err := url.ParseRequestURI(httpUser[0])
		if err != nil || urlParse.Host == "" {
			return nil, errors.New("这不是一个有效链接地址!")
		}
		GitLabServer := urlParse.Scheme + "://" + urlParse.Host
		if urlParse.User == nil {
			git, err = gitlab.NewClient(
				"",
				gitlab.WithBaseURL(GitLabServer),
			)
		} else {
			Password, rs := urlParse.User.Password()
			if !rs {
				return nil, errors.New("链接密码丢失")
			}
			if urlParse.User.Username() == "" {
				return nil, errors.New("链接账号丢失")
			}
			GitLabUser := urlParse.User.Username()
			GitLabPwd := Password

			if GitLabUser == "oauth2" {
				git, err = gitlab.NewClient(
					GitLabPwd,
					gitlab.WithBaseURL(GitLabServer),
				)
			} else {
				git, err = gitlab.NewBasicAuthClient(
					GitLabUser,
					GitLabPwd,
					gitlab.WithBaseURL(GitLabServer),
				)
			}
		}
	} else {
		//内置账号密码
		config := ymlgo.NewConfigSysBase()
		userOauthModel := NewUserOauth()
		userOauth, _ := userOauthModel.One(uint(uid))
		GitLabUser := userOauth.GitLabUser
		GitLabPwd := userOauth.GitLabPwd
		GitLabServer := config.GitLabServer
		git, err = gitlab.NewBasicAuthClient(
			GitLabUser,
			GitLabPwd,
			gitlab.WithBaseURL(GitLabServer),
		)
	}

	if err != nil {
		return nil, errors.New("链接验证失败 :" + err.Error())
	}

	gitLab := &GitUserLab{
		Client: git,
	}
	return gitLab, nil
}

// 递归获取所属账号的仓库列表
func (m *GitUserLab) AllRepoList() []gitlab.Project {
	RepoList := []gitlab.Project{}
	m.gitLabRepoList(1, &RepoList)
	return RepoList
}

func (m *GitUserLab) GetGitForServerUrl(_url string) *gitlab.Project {
	urlParse, err := url.Parse(_url)
	if err != nil {
		return &gitlab.Project{}
	}
	search := strings.Split(strings.Replace(urlParse.Path, ".git", "", -1), "/")
	if len(search) < 3 {
		return &gitlab.Project{}
	}
	ListTreeOptions := &gitlab.ListProjectsOptions{
		//Membership: gitlab.Bool(true),
		Search: gitlab.String(search[len(search)-1]),
		Simple: gitlab.Bool(true),
	}

	TreeNodes, _, err := m.Client.Projects.ListProjects(ListTreeOptions)
	if err != nil {
		return &gitlab.Project{}
	}
	for _, v := range TreeNodes {
		if v.HTTPURLToRepo == urlParse.Scheme+"://"+urlParse.Host+urlParse.Path {
			return v
		}
	}
	return &gitlab.Project{}
}

func (m *GitUserLab) gitLabRepoList(page uint, list *[]gitlab.Project) {
	ListTreeOptions := &gitlab.ListProjectsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    int(page),
			PerPage: 100,
		},
		Membership: gitlab.Bool(true),
	}
	TreeNodes, _, _ := m.Client.Projects.ListProjects(ListTreeOptions)
	if len(TreeNodes) > 0 {
		for _, v := range TreeNodes {
			*list = append(*list, *v)
		}
		m.gitLabRepoList(page+1, list)
	}
}

// 递归获取已存在仓库中的文件列表
func (m *GitUserLab) AllFileList(Project int, ref, path string) []gitlab.TreeNode {
	TreeNodes := []gitlab.TreeNode{}
	m.gitLabFileList(Project, 1, ref, path, &TreeNodes)
	return TreeNodes
}

func (m *GitUserLab) gitLabFileList(ProjectId int, page uint, ref string, path string, list *[]gitlab.TreeNode) {
	ListTreeOptions := &gitlab.ListTreeOptions{
		ListOptions: gitlab.ListOptions{
			Page:    int(page),
			PerPage: 100,
		},
		Recursive: gitlab.Bool(false),
		Path:      gitlab.String(path),
		Ref:       gitlab.String(ref),
	}
	TreeNodes, _, _ := m.Client.Repositories.ListTree(ProjectId, ListTreeOptions)
	if len(TreeNodes) > 0 {
		for _, v := range TreeNodes {
			*list = append(*list, *v)
		}
		m.gitLabFileList(ProjectId, page+1, ref, path, list)
	}
}

// 递归获取提交注释
func (m *GitUserLab) AllCommitsList(Project int, ref, path string) []gitlab.Commit {
	Commits := []gitlab.Commit{}
	m.gitLabCommitsList(Project, 1, ref, path, &Commits)
	return Commits
}

func (m *GitUserLab) gitLabCommitsList(ProjectId int, page uint, ref string, path string, list *[]gitlab.Commit) {
	ListCommitsOptions := &gitlab.ListCommitsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    int(page),
			PerPage: 100,
		},
		Path: gitlab.String(path),
	}
	Commits, _, _ := m.Client.Commits.ListCommits(ProjectId, ListCommitsOptions)
	if len(Commits) > 0 {
		for _, v := range Commits {
			*list = append(*list, *v)
		}
		m.gitLabCommitsList(ProjectId, page+1, ref, path, list)
	}
}

// GetCommits 根据分支和ProjectId 获取提交记录
func (m *GitUserLab) GetCommits(ProjectId int, ref string, page, perPage int, start, end string) ([]*gitlab.Commit, gitlab.Response) {
	ListCommitsOptions := &gitlab.ListCommitsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    page,
			PerPage: perPage,
		},
		RefName: gitlab.String(ref),
	}
	if start != "" && end != "" {
		since, _ := time.ParseInLocation("2006-01-02 15:04:05", start, time.Local)
		until, _ := time.ParseInLocation("2006-01-02 15:04:05", end, time.Local)
		ListCommitsOptions.Since = &since
		ListCommitsOptions.Until = &until
	}
	Commit, resp, err := m.Client.Commits.ListCommits(strconv.Itoa(ProjectId), ListCommitsOptions)
	if err != nil {
		fmt.Println(`err: `, err.Error())
	}
	if resp == nil {
		return Commit, gitlab.Response{}
	}
	return Commit, *resp
}

// 获取git提交文件差异对比
func (m *GitUserLab) GetCommitDiff(ProjectId int, sha string) ([]*gitlab.Diff, error) {
	listOptions := &gitlab.GetCommitDiffOptions{
		Page:    1,
		PerPage: 200,
	}
	diffArr, _, err := m.Client.Commits.GetCommitDiff(ProjectId, sha, listOptions)
	if err != nil {
		return nil, errors.New(err.Error())
	}
	return diffArr, nil
}

// AddProjectMember 将用户添加到某一个工程
func (m *GitUserLab) AddProjectMember(pid, uid int, accessLevel gitlab.AccessLevelValue, expireAt string) (*gitlab.ProjectMember, error) {
	opt := &gitlab.AddProjectMemberOptions{
		UserID:      gitlab.Int(uid),
		AccessLevel: gitlab.AccessLevel(accessLevel),
	}
	if expireAt != "" {
		opt.ExpiresAt = gitlab.String(expireAt)
	}
	projectMember, _, err := m.Client.ProjectMembers.AddProjectMember(pid, opt)
	if err != nil {
		return nil, errors.New(err.Error())
	}
	return projectMember, nil
}

func (m *GitLab) AddProjectMember(pid, uid int, accessLevel gitlab.AccessLevelValue, expireAt string) (*gitlab.ProjectMember, error) {
	opt := &gitlab.AddProjectMemberOptions{
		UserID:      gitlab.Int(uid),
		AccessLevel: gitlab.AccessLevel(accessLevel),
	}
	if expireAt != "" {
		opt.ExpiresAt = gitlab.String(expireAt)
	}
	projectMember, _, err := m.Client.ProjectMembers.AddProjectMember(pid, opt)
	if err != nil {
		return nil, errors.New(err.Error())
	}
	return projectMember, nil
}

// GetProjectMember 获取工程成员
func (m *GitUserLab) GetProjectMember(pid int, query string) ([]*gitlab.ProjectMember, error) {
	opt := &gitlab.ListProjectMembersOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 200,
		},
	}
	if query != "" {
		opt.Query = gitlab.String(query)
	}
	members, _, err := m.Client.ProjectMembers.ListProjectMembers(pid, opt)
	if err != nil {
		fmt.Println(err.Error())
		return nil, errors.New("获取用户信息失败")
	}

	return members, nil
}

// 改变用户在工程内的角色和过期时间
// # https://docs.gitlab.com/ce/api/members.html#edit-a-member-of-a-group-or-project
func (m *GitUserLab) EditProjectMemberRole(pid, uid int, accessLevel int, expireAt string) error {
	opt := &gitlab.EditProjectMemberOptions{
		AccessLevel: gitlab.AccessLevel(gitlab.AccessLevelValue(accessLevel)),
		ExpiresAt:   gitlab.String(expireAt), // 参数必传
	}

	_, _, err := m.Client.ProjectMembers.EditProjectMember(pid, uid, opt)

	return err
}

// 工程分享到群组
// # https://docs.gitlab.com/ee/api/projects.html#share-project-with-group
func (m *GitUserLab) ShareProjectWithGroup(pid, groupId int, groupAccess int, expiresAt string) error {
	opt := &gitlab.ShareWithGroupOptions{
		GroupID:     gitlab.Int(groupId),
		GroupAccess: gitlab.AccessLevel(gitlab.AccessLevelValue(groupAccess)),
	}
	if expiresAt != "" {
		opt.ExpiresAt = gitlab.String(expiresAt)
	}
	_, err := m.Client.Projects.ShareProjectWithGroup(pid, opt)

	return err
}

// 删除共享的群组
// #https://docs.gitlab.com/ee/api/projects.html#delete-a-shared-project-link-within-a-group
func (m *GitUserLab) DeleteSharedProjectFromGroup(pid, groupId int) error {
	_, err := m.Client.Projects.DeleteSharedProjectFromGroup(pid, groupId)
	return err
}

// 将用户从工程中删除
func (m *GitUserLab) DeleteProjectMember(pid, uid int) error {
	_, err := m.Client.ProjectMembers.DeleteProjectMember(pid, uid)
	return err
}

// 获取所有的工程
func (m *GitUserLab) GetAllProject(name string) ([]*gitlab.Project, error) {
	opt := &gitlab.ListProjectsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 100,
		},
		Visibility: gitlab.Visibility(gitlab.PublicVisibility),
	}
	if name != "" {
		opt.Search = gitlab.String(name)
	}
	projects, _, err := m.Client.Projects.ListProjects(opt)
	return projects, err
}

// 获取工程的详细信息
func (m *GitUserLab) GetProjectInfo(pid int) (*gitlab.Project, error) {
	opt := &gitlab.GetProjectOptions{}
	project, _, err := m.Client.Projects.GetProject(pid, opt)
	if err != nil {
		return nil, errors.New(err.Error())
	}

	return project, nil
}

// GetNormalUsers 获取普通用户根据username模糊搜索
func (m *GitLab) GetNormalUsers(username string) ([]*gitlab.User, error) {
	listUserOptions := &gitlab.ListUsersOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 200,
		},
		Active: gitlab.Bool(true),
	}
	if username != "" {
		listUserOptions.Search = gitlab.String(username)
	}
	users, _, err := m.Client.Users.ListUsers(listUserOptions)
	if err != nil {
		return nil, errors.New(err.Error())
	}

	return users, nil
}

// 获取所有当前授权用户拥有的组 #https://docs.gitlab.com/ee/api/groups.html#list-groups
func (m *GitUserLab) GetMyGroups() ([]*gitlab.Group, error) {
	opt := &gitlab.ListGroupsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 100,
		},
		Owned: gitlab.Bool(true),
	}
	groups, _, err := m.Client.Groups.ListGroups(opt)

	return groups, err
}

/**
获取分支 支持搜索
*/
func (m *GitUserLab) GetAllBranches(pid int, search string) ([]*gitlab.Branch, error) {
	BranchesOptions := &gitlab.ListBranchesOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 100,
		},
	}
	if search != "" {
		BranchesOptions.Search = gitlab.String(search)
	}
	Branched, _, err := m.Client.Branches.ListBranches(pid, BranchesOptions)

	return Branched, err
}

/**
创建分支
branch 分支名
ref create from
*/
func (m *GitUserLab) CreateBranch(pid int, branch, ref string) (*gitlab.Branch, error) {
	opt := &gitlab.CreateBranchOptions{
		Branch: gitlab.String(branch),
		Ref:    gitlab.String(ref),
	}
	res, _, err := m.Client.Branches.CreateBranch(pid, opt)
	return res, err
}

/**
删除分支
*/
func (m *GitUserLab) DeleteBranch(pid int, branchName string) error {
	_, err := m.Client.Branches.DeleteBranch(pid, branchName)
	return err
}

// 删除已合并的分支
func (m *GitUserLab) DeleteMergedBranch(pid int) error {
	_, err := m.Client.Branches.DeleteMergedBranches(pid)
	return err
}

func (m *GitUserLab) GetCommitDetail(pid int, sha string) (*gitlab.Commit, error) {
	commit, _, err := m.Client.Commits.GetCommit(pid, sha)
	return commit, err
}

// 获取所有tag 可按时间名称排序  gitlab 11.8支持search
// #https://docs.gitlab.com/ee/api/tags.html#list-project-repository-tags
func (m *GitUserLab) GetAllTag(pid int, orderBy, sort, search string) ([]*gitlab.Tag, error) {
	opt := &gitlab.ListTagsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 200,
		},
		OrderBy: gitlab.String(orderBy),
		Sort:    gitlab.String(sort),
	}
	tags, _, err := m.Client.Tags.ListTags(pid, opt)
	if err != nil {
		return nil, err
	}
	if search != "" {
		searchTag := make([]*gitlab.Tag, 0)
		for _, v := range tags {
			if strings.Contains(v.Name, search) {
				searchTag = append(searchTag, v)
			}
		}

		return searchTag, nil
	}

	return tags, err
}

// 创建tag
func (m *GitUserLab) CreateTag(pid int, tagName, ref, message, desc string) (*gitlab.Tag, error) {
	opt := &gitlab.CreateTagOptions{
		TagName:            gitlab.String(tagName),
		Ref:                gitlab.String(ref),
		Message:            gitlab.String(message),
		ReleaseDescription: gitlab.String(desc),
	}
	tag, _, err := m.Client.Tags.CreateTag(pid, opt)

	return tag, err
}

// 更新tag描述
func (m *GitUserLab) EditTag(pid int, tag, desc string) (*gitlab.ReleaseNote, error) {
	opt := &gitlab.UpdateReleaseNoteOptions{
		Description: gitlab.String(desc),
	}
	note, _, err := m.Client.Tags.UpdateReleaseNote(pid, tag, opt)
	return note, err
}

// 删除标签
func (m *GitUserLab) DeleteTag(pid int, tag string) error {
	_, err := m.Client.Tags.DeleteTag(pid, tag)
	return err
}

// 获取合并请求
func (m *GitUserLab) GetProjectMergeRequest(pid int, state, search string) ([]*gitlab.MergeRequest, error) {
	opt := &gitlab.ListProjectMergeRequestsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 200,
		},
		State:   gitlab.String(state),
		OrderBy: gitlab.String("updated_at"),
		Sort:    gitlab.String("desc"),
		Search:  gitlab.String(search),
	}
	mergeRequest, _, err := m.Client.MergeRequests.ListProjectMergeRequests(pid, opt)
	return mergeRequest, err
}

// 编辑合并请求
func (m *GitUserLab) EditMergeRequest(pid, mergeRequest int, opt *gitlab.UpdateMergeRequestOptions) (*gitlab.MergeRequest, error) {
	mr, _, err := m.Client.MergeRequests.UpdateMergeRequest(pid, mergeRequest, opt)
	return mr, err
}

// DeleteMergeRequest 删除合并请求
func (m *GitUserLab) DeleteMergeRequest(pid, iid int) error {
	_, err := m.Client.MergeRequests.DeleteMergeRequest(pid, iid)
	return err
}

// 新建合并请求
func (m *GitUserLab) CreateMergeRequet(pid int, opt *gitlab.CreateMergeRequestOptions) (*gitlab.MergeRequest, error) {
	mr, _, err := m.Client.MergeRequests.CreateMergeRequest(pid, opt)
	return mr, err
}

// 接受合并请求
func (m *GitUserLab) AcceptMergeRequest(pid, mrId int, opt *gitlab.AcceptMergeRequestOptions) (*gitlab.MergeRequest, error) {
	mr, _, err := m.Client.MergeRequests.AcceptMergeRequest(pid, mrId, opt)
	return mr, err
}

// 获取合并请求的提交
func (m *GitUserLab) MergeRequestCommit(pid, iid, page int) ([]*gitlab.Commit, error) {
	opt := &gitlab.GetMergeRequestCommitsOptions{
		Page:    page,
		PerPage: 100,
	}
	commits, _, err := m.Client.MergeRequests.GetMergeRequestCommits(pid, iid, opt)
	return commits, err
}

// 获取工程的标签
func (m *GitUserLab) GetProjectLabels(pid int) ([]*gitlab.Label, error) {
	opt := &gitlab.ListLabelsOptions{
		Page:    1,
		PerPage: 100,
	}
	labels, _, err := m.Client.Labels.ListLabels(pid, opt)
	return labels, err
}

// 创建标签
func (m *GitUserLab) CreateLabelsForProject(pid int, name, color, desc string) (*gitlab.Label, error) {
	opt := &gitlab.CreateLabelOptions{
		Name:        gitlab.String(name),
		Color:       gitlab.String(color),
		Description: gitlab.String(desc),
	}
	label, _, err := m.Client.Labels.CreateLabel(pid, opt)
	return label, err
}

// 获取wiki列表
func (m *GitUserLab) GetWikiList(pid int) ([]*gitlab.Wiki, error) {
	opt := &gitlab.ListWikisOptions{
		WithContent: gitlab.Bool(false),
	}
	wikis, _, err := m.Client.Wikis.ListWikis(pid, opt)

	return wikis, err
}

// CreateWiki 创建wiki
func (m *GitUserLab) CreateWiki(pid int, content, title string) (*gitlab.Wiki, error) {
	opt := &gitlab.CreateWikiPageOptions{
		Content: gitlab.String(content),
		Title:   gitlab.String(title),
		Format:  gitlab.String("markdown"),
	}
	wiki, _, err := m.Client.Wikis.CreateWikiPage(pid, opt)
	return wiki, err
}

// EditWiki 编辑wiki
func (m *GitUserLab) EditWiki(pid int, slug, content, title string) (*gitlab.Wiki, error) {
	opt := &gitlab.EditWikiPageOptions{
		Content: gitlab.String(content),
		Title:   gitlab.String(title),
		Format:  gitlab.String("markdown"),
	}
	wiki, _, err := m.Client.Wikis.EditWikiPage(pid, slug, opt)
	return wiki, err
}

// GetWikiContent 获取单个wiki的详情
func (m *GitUserLab) GetWikiContent(pid int, slug string) (*gitlab.Wiki, error) {
	wiki, _, err := m.Client.Wikis.GetWikiPage(pid, slug)
	return wiki, err
}

// DeleteWiki 删除wiki
func (m *GitUserLab) DeleteWiki(pid int, slug string) error {
	_, err := m.Client.Wikis.DeleteWikiPage(pid, slug)
	return err
}

// AddSSHKey Creates a new key owned by the currently authenticated user.
func (m *GitUserLab) AddSSHKey(title, key string) (*gitlab.SSHKey, error) {
	opt := &gitlab.AddSSHKeyOptions{
		Title: gitlab.String(title),
		Key:   gitlab.String(key),
	}
	SSHKey, _, err := m.Client.Users.AddSSHKey(opt)

	return SSHKey, err
}

// ListSSHKeys  Get a list of currently authenticated user’s SSH keys.
func (m *GitUserLab) ListSSHKeys() ([]*gitlab.SSHKey, error) {
	SSHKeys, _, err := m.Client.Users.ListSSHKeys()
	return SSHKeys, err
}

/**
Delete SSH key for current user
Deletes key owned by currently authenticated user. This returns a 204 No Content status code if the operation was successfully or 404 if the resource was not found.
*/
func (m *GitUserLab) DeleteSSHKey(keyId int) error {
	_, err := m.Client.Users.DeleteSSHKey(keyId)
	return err
}

// ListAllGroup 获取群组
func (m *GitUserLab) ListAllGroup(owned bool, search string) ([]*gitlab.Group, error) {
	opt := &gitlab.ListGroupsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 200,
		},
		AllAvailable: gitlab.Bool(true),
		// OrderBy:      gitlab.String("id"),
		Owned:  gitlab.Bool(owned),
		Sort:   gitlab.String("desc"),
		Search: gitlab.String(search),
	}
	groups, _, err := m.Client.Groups.ListGroups(opt)
	return groups, err
}

// CreateGroup 创建群组
func (m *GitUserLab) CreateGroup(opt *gitlab.CreateGroupOptions) (*gitlab.Group, error) {
	group, _, err := m.Client.Groups.CreateGroup(opt)
	return group, err
}

// DeleteGroup 删除群组
func (m *GitUserLab) DeleteGroup(groupId int) error {
	_, err := m.Client.Groups.DeleteGroup(groupId)
	return err
}

// EditGroup 编辑群组
func (m *GitUserLab) EditGroup(groupId int, name, desc string, visibility gitlab.VisibilityValue) (*gitlab.Group, error) {
	opt := &gitlab.UpdateGroupOptions{
		Name:        gitlab.String(name),
		Description: gitlab.String(desc),
		Visibility:  gitlab.Visibility(visibility),
	}
	group, _, err := m.Client.Groups.UpdateGroup(groupId, opt)

	return group, err
}

// GroupDetail 获取群组详情
func (m *GitUserLab) GroupDetail(groupId int) (*gitlab.Group, error) {
	group, _, err := m.Client.Groups.GetGroup(groupId)
	return group, err
}

// GetSubGroups 获取所有子组
func (m *GitUserLab) GetSubGroups(groupId int) ([]*gitlab.Group, error) {
	opt := &gitlab.ListSubgroupsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 200,
		},
		AllAvailable: gitlab.Bool(true),
	}
	subGroups, _, err := m.Client.Groups.ListSubgroups(groupId, opt)
	return subGroups, err
}

// 检查当前用户对应的git账号是否在工程中
func (m *GitUserLab) CheckUserIsInProject(pid, uid int) (*gitlab.ProjectMember, error) {
	// 1.获取当前用户的git账号信息
	userOauthModel := NewUserOauth()
	userAuth, err := userOauthModel.One(uint(uid))
	if err != nil {
		return nil, errors.New("获取用户Git账号信息失败")
	}
	// 2.获取当前工程的拥有者判断用户是否有操作权限
	project, _, _ := m.Client.ProjectMembers.GetProjectMember(pid, int(userAuth.GitLabUserId))
	if project == nil {
		return nil, errors.New("非法请求:您不属于该工程,无此操作权限")
	}

	return project, nil
}

// 增加webhook
func (m *GitLab) AddWebhook(opt gitlab.AddHookOptions) error {
	_, _, err := m.Client.SystemHooks.AddHook(&opt)
	return err
}

// 获取工程下的分支
func (m *GitUserLab) GetBranches(ProjectId int, keywords string) []*gitlab.Branch {
	BranchesOptions := &gitlab.ListBranchesOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 100,
		},
		Search: gitlab.String(keywords),
	}
	Branched, _, _ := m.Client.Branches.ListBranches(ProjectId, BranchesOptions)

	return Branched
}

func (m *GitUserLab) GetTags(ProjectId int) []*gitlab.Tag {
	TagOptions := &gitlab.ListTagsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 100,
		},
	}
	Tags, _, _ := m.Client.Tags.ListTags(ProjectId, TagOptions)

	return Tags
}

func (m *GitLab) GetBranches(ProjectId int, keywords string) []*gitlab.Branch {
	BranchesOptions := &gitlab.ListBranchesOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 100,
		},
		Search: gitlab.String(keywords),
	}
	Branched, _, _ := m.Client.Branches.ListBranches(ProjectId, BranchesOptions)

	return Branched
}

func (m *GitLab) GetTags(ProjectId int) []*gitlab.Tag {
	TagOptions := &gitlab.ListTagsOptions{
		ListOptions: gitlab.ListOptions{
			Page:    1,
			PerPage: 100,
		},
	}
	Tags, _, _ := m.Client.Tags.ListTags(ProjectId, TagOptions)

	return Tags
}
